// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StrategyModelCell.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.Forge
{
    #region Using Directives

    using System;
    using System.Collections.Generic;

    using Org.OpenTrader.Framework.Enums;
    using Org.OpenTrader.Framework.Forge.Events;
    using Org.OpenTrader.Framework.Forge.Interfaces;
    using Org.OpenTrader.Framework.LinqKit;

    #endregion

    /// <summary>
    /// The strategy sector.
    /// </summary>
    public abstract class StrategyModelCell : IStrategyModelCell
    {
        #region Constants and Fields

        /// <summary>
        /// Basket : organised with index
        /// </summary>
        protected readonly IList<IInstrument> BasketIndex = new List<IInstrument>();

        /// <summary>
        /// Basket : organised with guid
        /// </summary>
        protected readonly IDictionary<Guid, IInstrument> BasketGuid = new Dictionary<Guid, IInstrument>();

        /// <summary>
        /// Basket : organised with code
        /// </summary>
        protected readonly IDictionary<string, IInstrument> BasketCode = new Dictionary<string, IInstrument>();
        
        /// <summary>
        /// The identity.
        /// </summary>
        private static readonly Identity Identity = Identity.Create(System.Reflection.MethodBase.GetCurrentMethod());

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="StrategyModelCell"/> class. 
        /// Constructor
        /// </summary>
        /// <param name="parent">
        /// The parent.
        /// </param>
        public StrategyModelCell(IStrategyModel parent)
        {
            Logging.Log(
                Identity, 
                ELogLevel.Debug, 
                () =>
                string.Format(
                    "StrategyModelCell : creating new StrategyModelCell {0}", 
                    (parent as StrategyPlugin) != null ? (parent as StrategyPlugin).Name : "Unknown Strategy Model"));
            this.Parent = parent;
            this.Name = string.Empty;
            this.Expo = new StrategyExpo();
            this.Status = EStrategyStatus.Stopped;
            this.StartAt = new TimeSpan();
            this.StopAt = new TimeSpan();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Config Table
        /// </summary>
        public Table Config { get; protected set; }

        /// <summary>
        /// Market Expo
        /// </summary>
        public StrategyExpo Expo { get; private set; }

        /// <summary>
        /// Sector Name
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// Strategy Model of this cell
        /// </summary>
        public IStrategyModel Parent { get; private set; }

        /// <summary>
        /// Starting time
        /// </summary>
        public TimeSpan StartAt { get; private set; }

        /// <summary>
        /// Status : Started, Stopped, Starting, Stopping
        /// </summary>
        public EStrategyStatus Status { get; private set; }

        /// <summary>
        /// Stopping time
        /// </summary>
        public TimeSpan StopAt { get; private set; }

        /// <summary>
        /// Number of parameters
        /// </summary>
        public abstract int NbParams { get; }

        #endregion

        #region Indexers

        /// <summary>
        /// Get Instrument using index
        /// </summary>
        /// <param name="index">indxex of the instrument</param>
        /// <returns></returns>
        public IInstrument this[int index]
        {
            get
            {
                return this.BasketIndex[index];
            }
        }

        /// <summary>
        /// Get Instrument using Code
        /// </summary>
        /// <param name="code">code of the instrument</param>
        /// <returns></returns>
        public IInstrument this[string code]
        {
            get
            {
                if (this.BasketCode.ContainsKey(code))
                {
                    return this.BasketCode[code];
                }

                return null;
            }
        }

        /// <summary>
        /// Get Instrument using Guid
        /// </summary>
        /// <param name="id">guid of the instrument</param>
        /// <returns></returns>
        public IInstrument this[Guid id]
        {
            get
            {
                if (this.BasketGuid.ContainsKey(id))
                {
                    return this.BasketGuid[id];
                }

                return null;
            }
        }
        
        #endregion

        #region Implemented Interfaces

        #region IStrategyModelCell

        /// <summary>
        /// Add the instrument i to the cell
        /// </summary>
        /// <param name="i">
        /// instrument i : not null
        /// </param>
        /// <returns>
        /// Return true if can add this instrument
        /// </returns>
        public bool Add(IInstrument i)
        {
            // Check if the Tracker is null
            if (this.Parent == null)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Add : Cannot add Instrument in {0}, Invalid Parent", this.Name));
                return false;
            }

            // Check parent as strategyPlugin
            if ((this.Parent as StrategyPlugin) == null)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Add : Cannot add Instrument in {0}, Parent is not a StrategyPluggin", this.Name));
                return false;
            }

            // Check if the instrument is null
            if (i == null)
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Error, 
                    () => string.Format("Add : Cannot add Instrument in {0} - {1}, Invalid Instrument", this.Name, ((StrategyPlugin)this.Parent).Name));
                return false;
            }

            if (i.InstrumentStaticData == null)
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Error, 
                    () =>
                    string.Format("Add : Cannot add Instrument in {0} - {1}, Invalid Instrument Static Data", this.Name, ((StrategyPlugin)this.Parent).Name));
                return false;
            }

            // Check if the instrument is already in the list
            var tmp = this[i.InstrumentStaticData.Code];
            if (tmp != null)
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Error, 
                    () =>
                    string.Format(
                        "Add : Cannot add Instrument in {0} - {1}, Instrument already used {2} ({3})", 
                        this.Name, 
                        ((StrategyPlugin)this.Parent).Name, 
                        i.InstrumentStaticData.Code, 
                        i.InstrumentStaticData.TradingScope));
                return false;
            }

            // subscribe to Feed & OrderTracker : StrategyModelCell & StrategyModel
            try
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Debug, 
                    () =>
                    string.Format(
                        "Add : Subscribing Instrument {0} ({1}) to Feed & Orders : {2} - {3}", 
                        i.InstrumentStaticData.Code, 
                        i.InstrumentStaticData.TradingScope, 
                        this.Name, 
                        ((StrategyPlugin)this.Parent).Name));

                // Subscribe the instrument to Feed 
                i.FeedEventCB += this.OnFeed;
                i.FeedEventCB += this.Parent.OnFeed;

                // Subscribe the instrument to Order Tracker 
                i.OrderTrackingEventCB += this.OnOrder;
                i.OrderTrackingEventCB += this.Parent.OnOrder;
            }
            catch
            {
                return false;
            }

            // Subscribe the instrument to the Expo
            this.Expo.Add(i);

            // Add instrument i to the Basket
            this.BasketIndex.Add(i);
            this.BasketCode.Add(i.InstrumentStaticData.Code, i);
            this.BasketGuid.Add(i.InstrumentStaticData.ID, i);

            Logging.Log(
                Identity, 
                ELogLevel.Debug, 
                () =>
                string.Format(
                    "Add : Instrument {0} ({1}) added : {2} - {3}", 
                    i.InstrumentStaticData.Code, 
                    i.InstrumentStaticData.TradingScope, 
                    this.Name, 
                    ((StrategyPlugin)this.Parent).Name));

            return true;
        }

        /// <summary>
        /// Add the instrument to the cell
        /// </summary>
        /// <param name="code">
        /// Code of the instrument : not empty
        /// </param>
        /// <returns>
        /// The add.
        /// </returns>
        public bool Add(string code)
        {
            // Check code
            if (code.Length == 0)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Add : Cannot add Instrument in {0}, Empty code", this.Name));
                return false;
            }

            // Check parent
            if (this.Parent == null)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Add : Cannot add Instrument in {0}, Invalid Parent", this.Name));
                return false;
            }

            // Check parent as strategyPlugin
            if ((this.Parent as StrategyPlugin) == null)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Add : Cannot add Instrument in {0}, Parent is not a StrategyPluggin", this.Name));
                return false;
            }

            // Check parent referential
            if ((this.Parent as StrategyPlugin).Referential == null)
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Error, 
                    () => string.Format("Add : Cannot add Instrument in {0} - {1}, Invalid Referential", this.Name, ((StrategyPlugin)this.Parent).Name));
                return false;
            }

            // Lookup for the instrument
            var lookupstatusasset = (this.Parent as StrategyPlugin).Referential.CreateInstrument(code, this.Parent.TradingScope);
            if (!lookupstatusasset)
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Error, 
                    () =>
                    string.Format(
                        "Add : Cannot add Instrument in {0} - {1}, InstrumentStaticData {2} not found", this.Name, ((StrategyPlugin)this.Parent).Name, code));
                return false;
            }

            return this.Add(lookupstatusasset.NestedObject);
        }

        /// <summary>
        /// Remove Instrument from baskets
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public bool Remove(IInstrument i)
        {
            // Check if the Tracker is null
            if (this.Parent == null)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Remove : Cannot Remove Instrument in {0}, Invalid Parent", this.Name));
                return false;
            }

            // Check parent as strategyPlugin
            if ((this.Parent as StrategyPlugin) == null)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Remove : Cannot Remove Instrument in {0}, Parent is not a StrategyPluggin", this.Name));
                return false;
            }

            // Check if the instrument is null
            if (i == null)
            {
                Logging.Log(
                    Identity,
                    ELogLevel.Error,
                    () => string.Format("Remove : Cannot Remove Instrument in {0} - {1}, Invalid Instrument", this.Name, ((StrategyPlugin)this.Parent).Name));
                return false;
            }

            if (i.InstrumentStaticData == null)
            {
                Logging.Log(
                    Identity,
                    ELogLevel.Error,
                    () =>
                    string.Format("Remove : Cannot Remove Instrument in {0} - {1}, Invalid Instrument Static Data", this.Name, ((StrategyPlugin)this.Parent).Name));
                return false;
            }

            // Check if the instrument is already in the list
            var tmp = this[i.InstrumentStaticData.Code];
            if (tmp == null)
            {
                Logging.Log(
                    Identity,
                    ELogLevel.Error,
                    () =>
                    string.Format(
                        "Remove : Cannot Remove Instrument in {0} - {1}, Unknown Instrument {2} ({3})",
                        this.Name,
                        ((StrategyPlugin)this.Parent).Name,
                        i.InstrumentStaticData.Code,
                        i.InstrumentStaticData.TradingScope));
                return false;
            }

            // Unsubscribe from Feed & OrderTracker : StrategyModelCell & StrategyModel
            try
            {
                Logging.Log(
                    Identity,
                    ELogLevel.Debug,
                    () =>
                    string.Format(
                        "Remove : UnSubscribing Instrument {0} ({1}) from Feed & Orders : {2} - {3}",
                        i.InstrumentStaticData.Code,
                        i.InstrumentStaticData.TradingScope,
                        this.Name,
                        ((StrategyPlugin)this.Parent).Name));

                // Subscribe the instrument to Feed 
                i.FeedEventCB -= this.OnFeed;
                i.FeedEventCB -= this.Parent.OnFeed;

                // Subscribe the instrument to Order Tracker 
                i.OrderTrackingEventCB -= this.OnOrder;
                i.OrderTrackingEventCB -= this.Parent.OnOrder;
            }
            catch
            {
                return false;
            }

            // UnSubscribe the instrument from the Expo
            this.Expo.Remove(i);

            // Add instrument i to the Basket
            this.BasketIndex.Remove(i);
            this.BasketCode.Remove(i.InstrumentStaticData.Code);
            this.BasketGuid.Remove(i.InstrumentStaticData.ID);

            Logging.Log(
                Identity,
                ELogLevel.Debug,
                () =>
                string.Format(
                    "Remove : Instrument {0} ({1}) Removed : {2} - {3}",
                    i.InstrumentStaticData.Code,
                    i.InstrumentStaticData.TradingScope,
                    this.Name,
                    ((StrategyPlugin)this.Parent).Name));

            return true;
        }
        
        /// <summary>
        /// Remove Instrument from the list
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public bool Remove(string code)
        {
            // Check code
            if (code.Length == 0)
            {
                Logging.Log(Identity, ELogLevel.Error, () => string.Format("Remove : Cannot Remove Instrument in {0}, Empty code", this.Name));
                return false;
            }

            IInstrument i = this[code];
            return this.Remove(i);
        }

        /// <summary>
        /// Remove Instrument from the list
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Remove(Guid id)
        {
            IInstrument i = this[id];
            return this.Remove(i);
        }
        
        /// <summary>
        /// Cancel Buy orders of this sector
        /// </summary>
        /// <returns>
        /// The cancel buy orders.
        /// </returns>
        public int CancelBuyOrders()
        {
            Logging.Log(
                Identity, 
                ELogLevel.Debug, 
                () => string.Format("CancelBuyOrders : Cancelling Buy Orders of all Instruments {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));

            var nb = 0;
            foreach (var i in this.BasketIndex)
            {
                nb += i.CancelAllBuy();
            }

            return nb;
        }

        /// <summary>
        /// Cancel all orders of this sector
        /// </summary>
        /// <returns>
        /// The cancel orders.
        /// </returns>
        public int CancelOrders()
        {
            Logging.Log(
                Identity, 
                ELogLevel.Debug, 
                () => string.Format("CancelOrders : Cancelling All Orders of all Instruments {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));

            var nb = 0;
            foreach (var i in this.BasketIndex)
            {
                nb += i.CancelAll();
            }

            return nb;
        }

        /// <summary>
        /// Cancel Sell orders of this sector
        /// </summary>
        /// <returns>
        /// The cancel sell orders.
        /// </returns>
        public int CancelSellOrders()
        {
            Logging.Log(
                Identity, 
                ELogLevel.Debug, 
                () => string.Format("CancelSellOrders : Cancelling Sell Orders of all Instruments {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));

            var nb = 0;
            foreach (var i in this.BasketIndex)
            {
                nb += i.CancelAllSell();
            }

            return nb;
        }

        /// <summary>
        /// Check starting parameters before starting this sector
        /// </summary>
        /// <param name="time">
        /// The time : now
        /// </param>
        /// <returns>
        /// The check starting.
        /// </returns>
        public virtual bool CheckStarting(TimeSpan time)
        {
            // TODO check parameters and status

            // Check StartAt & StopAt
            if (TimeSpan.Compare(time, this.StartAt) >= 0 && TimeSpan.Compare(time, this.StopAt) <= 0)
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Debug, 
                    () => string.Format("CheckStarting : valid StartAt & StopAt {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
                return true;
            }

            Logging.Log(
                Identity, 
                ELogLevel.Error, 
                () => string.Format("CheckStarting : invalid StartAt & StopAt {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));

            return false;
        }

        /// <summary>
        /// Get Nb Instrument where status
        /// </summary>
        /// <param name="status">
        /// Enabled, BuyEnabled, SellEnabled, Restricted ...
        /// </param>
        /// <returns>
        /// The nb of instruments using status
        /// </returns>
        public int Nb(EInstrumentStatus status)
        {
            if (status == 0)
            {
                return this.BasketIndex.Count;
            }

            var nb = 0;
            foreach (var i in this.BasketIndex)
            {
                if (i != null)
                {
                    if (i.InstrumentStaticData != null)
                    {
                        if (status == EInstrumentStatus.Enabled && i.InstrumentStaticData.Enabled)
                        {
                            nb++;
                        }
                        else if (status == EInstrumentStatus.BuyEnabled && i.InstrumentStaticData.BuyEnabled)
                        {
                            nb++;
                        }
                        else if (status == EInstrumentStatus.SellEnabled && i.InstrumentStaticData.SellEnabled)
                        {
                            nb++;
                        }
                        else if (status == EInstrumentStatus.ShortSellEnabled && i.InstrumentStaticData.ShortSellEnabled)
                        {
                            nb++;
                        }
                        else if (status == EInstrumentStatus.HardToBorrow && i.InstrumentStaticData.HardToBorrow)
                        {
                            nb++;
                        }
                        else if (status == EInstrumentStatus.Restricted && i.InstrumentStaticData.Restricted)
                        {
                            nb++;
                        }
                        else if (status == EInstrumentStatus.BlackListed && i.InstrumentStaticData.BlackListed)
                        {
                            nb++;
                        }
                    }
                }
            }

            return nb;
        }

        /// <summary>
        /// OnFeed event
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="args">
        /// </param>
        public abstract void OnFeed(object sender, FeedEventArgs args);

        /// <summary>
        /// OnOrder reply
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="args">
        /// </param>
        public abstract void OnOrder(object sender, OrderTrackingEventArgs args);

        /// <summary>
        /// Synchronous run
        /// </summary>
        public virtual void Run()
        {
            // Get Time
            var now = Timings.Now.TimeOfDay;

            // Check status
            if (this.Status == EStrategyStatus.Started)
            {
                // It is started
                if (TimeSpan.Compare(now, this.StopAt) >= 0)
                {
                    // Auto stop
                    this.Stop();
                }
            }
            else if (this.Status == EStrategyStatus.Stopping)
            {
                // is stopping, check pending orders and wait till all the orders are closed
                var canstop = true;

                // Pending orders
                var predicatePending = PredicateBuilder.True<IOrderTrackingCell>();
                predicatePending = predicatePending.And(cell => cell.Pending);

                // Open Orders
                var predicateOpen = PredicateBuilder.True<IOrderTrackingCell>();
                predicateOpen = predicateOpen.And(cell => cell.Open);

                foreach (var i in this.BasketIndex)
                {
                    if (i != null)
                    {
                        // get pending orders
                        var cells = i.OrderTracker.GetTrackingCells(predicatePending);
                        if (cells != null)
                        {
                            if (cells.Length > 0)
                            {
                                // do not stop
                                canstop = false;

                                // Cancel open orders
                                var cellsOpen = i.OrderTracker.GetTrackingCells(predicateOpen);
                                if (cellsOpen != null)
                                {
                                    if (cellsOpen.Length > 0)
                                    {
                                        i.CancelAll();
                                    }
                                }
                            }
                        }
                    }
                }

                // No Order is pending or open
                if (canstop)
                {
                    this.Status = EStrategyStatus.Stopped;
                }
            }
            else if (this.Status == EStrategyStatus.Starting)
            {
                // is starting
                // Check starting parameters
                if (this.CheckStarting(now))
                {
                    // Starting params are ok
                    this.Status = EStrategyStatus.Started;
                }
                else
                {
                    // cannot start the sector
                    this.Status = EStrategyStatus.Stopped;
                }
            }
            else if (this.Status == EStrategyStatus.Stopped)
            {
                // It is stopped

                // Nothing to do
            }
        }

        /// <summary>
        /// Set Parameters
        /// </summary>
        /// <param name="key">
        /// name of the parameter : not empty
        /// </param>
        /// <param name="val">
        /// the value of the parameter : not empty
        /// </param>
        /// <returns>
        /// The set param.
        /// </returns>
        public virtual bool SetParam(string key, Table.Cell val)
        {
            // check & set parameters using key/value
            if (key.Length == 0 || val == null)
            {
                Logging.Log(
                    Identity, 
                    ELogLevel.Error, 
                    () => string.Format("SetParam : invalid param, empty key/value : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
                return false;
            }

            // Name
            if (key == "Name")
            {
                if (this.Status == EStrategyStatus.Stopped)
                {
                    this.Name = val;
                    return true;
                }
                else
                {
                    Logging.Log(
                        Identity, 
                        ELogLevel.Error, 
                        () => string.Format("SetParam : cannot set Name, strategy not stopped : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
                    return false;
                }
            }

            // StartAt
            if (key == "StartAt")
            {
                if (this.Status == EStrategyStatus.Stopped)
                {
                    var tmp = new TimeSpan();
                    var ret = TimeSpan.TryParse(val, out tmp);
                    this.StartAt = tmp;
                    return ret;
                }
                else
                {
                    Logging.Log(
                        Identity, 
                        ELogLevel.Error, 
                        () => string.Format("SetParam : cannot set StartAt, strategy not stopped : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
                    return false;
                }
            }

            // StopAt
            if (key == "StopAt")
            {
                if (this.Status == EStrategyStatus.Stopped)
                {
                    var tmp = new TimeSpan();
                    var ret = TimeSpan.TryParse(val, out tmp);
                    this.StopAt = tmp;
                    return ret;
                }
                else
                {
                    Logging.Log(
                        Identity, 
                        ELogLevel.Error, 
                        () => string.Format("SetParam : cannot set StopAt, strategy not stopped : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
                    return false;
                }
            }

            Logging.Log(
                Identity, ELogLevel.Error, () => string.Format("SetParam : invalid param, key ({0})/value({1}) : {2} - {3}", key, val, this.Name, ((StrategyPlugin)this.Parent).Name));
            return false;
        }

        /// <summary>
        /// Start : stopped -- starting
        /// </summary>
        /// <returns>
        /// The start.
        /// </returns>
        public virtual bool Start()
        {
            if (this.Status == EStrategyStatus.Stopped)
            {
                this.Status = EStrategyStatus.Starting;
                Logging.Log(Identity, ELogLevel.Debug, () => string.Format("Start : Starting : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
                return true;
            }

            Logging.Log(Identity, ELogLevel.Error, () => string.Format("Start : cannot start : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
            return false;
        }

        /// <summary>
        /// Stop : started -- stopping
        /// </summary>
        /// <returns>
        /// Return true if can stopping
        /// </returns>
        public virtual bool Stop()
        {
            if (this.Status == EStrategyStatus.Started)
            {
                this.Status = EStrategyStatus.Stopping;
                this.CancelOrders();
                Logging.Log(Identity, ELogLevel.Debug, () => string.Format("Stop : Stopping : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
                return true;
            }

            Logging.Log(Identity, ELogLevel.Error, () => string.Format("Stop : cannot stop : {0} - {1}", this.Name, ((StrategyPlugin)this.Parent).Name));
            return false;
        }

        #endregion

        #endregion
    }
}